// needed wx classes
#include <wx/fileconf.h>
#include <wx/stdpaths.h>
#include <wx/choicdlg.h>
#include <wx/clipbrd.h>

#include <sdk.h> // Code::Blocks SDK
#include <cbstyledtextctrl.h>
#include <configurationpanel.h>
#include "CodePaste.h"
#include "CodePasteUtils.h"
#include "CodePasteConfig.h"

static CodePasteSettings *settings;

// Register the plugin with Code::Blocks.
// We are using an anonymous namespace so we don't litter the global one.
namespace
{
    PluginRegistrant<CodePaste> reg(_T("CodePaste"));
    const int ID_PASTEBIN = wxNewId();
}

// events handling
BEGIN_EVENT_TABLE(CodePaste, cbPlugin)
    EVT_MENU(ID_PASTEBIN, CodePaste::OnPasteBin)
END_EVENT_TABLE()

// constructor
CodePaste::CodePaste()
{
    if(!Manager::LoadResource(_T("CodePaste.zip")))
    {
        NotifyMissingFile(_T("CodePaste.zip"));
    }
}

// destructor
CodePaste::~CodePaste()
{
}

void CodePaste::OnAttach()
{
   settings = new CodePasteSettings;
   LoadConfiguration();
}

void CodePaste::OnRelease(bool appShutDown)
{
   SaveConfiguration();
   delete settings;
}

void CodePaste::BuildMenu(wxMenuBar* menuBar)
{

   int editmenuInd = menuBar->FindMenu( _T("&Edit") );
   if(editmenuInd == wxNOT_FOUND )
      return;
   wxMenu* editMenu = menuBar->GetMenu(editmenuInd);
   if(!editMenu)
      return;

   wxString prefix = ConfigManager::GetDataFolder() + _T("/images/");

   wxMenuItemList& list = editMenu->GetMenuItems(); int pos = 0;
   // Search for the Recent files entry and insert the diff entry after it
   for(wxMenuItemList::iterator i = list.begin(); i != list.end(); ++i, ++pos)
   {
      wxMenuItem* item = *i;
      wxString label = item->GetLabel();
      label.Replace(_T("_"),_T(""));
      if(label.Contains(_T("Paste")))
      {
         editMenu->InsertSeparator(pos+1);
         wxMenuItem *newitem = new wxMenuItem(editMenu, ID_PASTEBIN, _T("Paste online"), _T("Copies the selected source code and pastes it in pastebin.com"));
         editMenu->Insert(pos+2, newitem);
         return;
      }
   }
}

void CodePaste::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data)
{
   switch(type)
   {
   case mtEditorManager:
      wxString prefix = ConfigManager::GetDataFolder() + _T("/images/");

      wxMenuItemList& list = menu->GetMenuItems(); int pos = 0;
      for(wxMenuItemList::iterator i = list.begin(); i != list.end(); ++i, ++pos)
      {
         wxMenuItem* item = *i;
         wxString label = item->GetLabel(); label.Replace(_T("_"),_T(""));
         if(label.Contains(_T("Edit")) && item->IsSubMenu() )
         {
            wxMenu *edit = item->GetSubMenu();
            edit->AppendSeparator();
            wxMenuItem *newitem = new wxMenuItem(edit, ID_PASTEBIN, _T("Paste online"), _T("Copies the selected source code and pastes it in pastebin.com"));
            //newitem->SetBitmap(wxBitmap(prefix+_T("paste_online.png"),wxBITMAP_TYPE_PNG));
            edit->Append(newitem);
            break;
         }
      }
      break;
   }
}

cbConfigurationPanel* CodePaste::GetConfigurationPanel(wxWindow *parent)
{ return new CodePasteConfigurationPanel(parent, settings); }

void CodePaste::LoadConfiguration()
{
   wxString filename = ConfigManager::GetConfigFolder() + _T("/CodePaste.ini");
   wxFileConfig cfg(wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);

   cfg.Read(_T("general/dev_key"), &(settings->dev_key), _T(""));
   cfg.Read(_T("general/default_title"), &(settings->default_title), _T("Untitled"));
   cfg.Read(_T("general/confirm_title"), &(settings->confirm_title), false );
   cfg.Read(_T("general/privacy"), &(settings->exposure_choice), 0);
   cfg.Read(_T("general/expires"), &(settings->expiration_choice), 2);
   cfg.Read(_T("general/syntax"), &(settings->syntax_choice), 31);
   cfg.Read(_T("general/auto_syntax"), &(settings->auto_syntax), false);
   cfg.Read(_T("ui/copy_link"), &(settings->copy_to_clipboard), true);
   cfg.Read(_T("ui/open_link"), &(settings->open_in_browser), true);
   cfg.Read(_T("network/timeout"), &(settings->timeout), 5);
}

void CodePaste::SaveConfiguration()
{
   wxString filename = ConfigManager::GetConfigFolder() + _T("/CodePaste.ini");
   wxFileConfig cfg(wxEmptyString, wxEmptyString, filename, wxEmptyString, wxCONFIG_USE_LOCAL_FILE);

   cfg.Write(_T("general/dev_key"), settings->dev_key);
   cfg.Write(_T("general/default_title"), settings->default_title);
   cfg.Write(_T("general/confirm_title"), settings->confirm_title);
   cfg.Write(_T("general/privacy"), settings->exposure_choice);
   cfg.Write(_T("general/expires"), settings->expiration_choice);
   cfg.Write(_T("general/syntax"), settings->syntax_choice);
   cfg.Write(_T("general/auto_syntax"), settings->auto_syntax);
   cfg.Write(_T("ui/copy_link"), settings->copy_to_clipboard);
   cfg.Write(_T("ui/open_link"), settings->open_in_browser);
   cfg.Write(_T("network/timeout"), settings->timeout);
}

void CodePaste::OnPasteBin(wxCommandEvent& event)
{
   if(this->IsAttached())
   {
      EditorBase *ed = Manager::Get()->GetEditorManager()->GetActiveEditor();
      if(ed->IsBuiltinEditor() && ed->HasSelection())
      {
         cbStyledTextCtrl *sted = ((cbEditor*) ed)->GetControl();
         wxString code = sted->GetSelectedText();
         if(code != _T(""))
         {
            wxString title = settings->default_title;
            int synchoice = settings->syntax_choice;

            if(settings->confirm_title)
               title = wxGetTextFromUser(_T("Enter the desired paste title."), _T("Paste Title"), title);

            if(settings->auto_syntax)
            {
               wxString fnam = ed->GetFilename().AfterLast(_T('\\')).AfterLast(_T('/'));
               wxString ext = fnam.AfterLast(_T('.'));
               // handle some special cases here:
               if(ext == _T("cs")) ext = _T("csharp");
               if(ext == _T("cxx") || ext == _T("hpp") || ext == _T("h")) ext = _T("cpp");
               if(ext == _T("di")) ext = _T("d");
               if(ext == _T("f74") || ext == _T("f95") || ext == _T("f")) ext = _T("fortran");
               if(ext == _T("iss")) ext = _T("inno");
               if(ext == _T("nsi")) ext = _T("nsis");
               if(ext == _T("pas")) ext = _T("pascal");
               if(ext == _T("py")) ext = _T("python");
               if(ext == _T("") || ext == _T("log") || ext == _T("txt")) ext = _T("text");
               bool match = false;
               for(int i = 0; !match && i < numSyntaxes; ++i)
               {
                  if(ext == syntaxes[i].code)
                  {
                     synchoice = i;
                     match = true;
                  }
               }
            }

            wxString params = _T("api_dev_key="); params += settings->dev_key;
            params += _T("&api_option=paste");
            params += _T("&api_paste_name="); params += wxURLEncode(title);
            params += _T("&api_paste_private="); params += (settings->exposure_choice ? _T("1") : _T("0"));
            params += _T("&api_paste_expire_date="); params += expirations[settings->expiration_choice].code;
            params += _T("&api_paste_format="); params += syntaxes[synchoice].code;
            params += _T("&api_paste_code="); params += wxURLEncode(code);
            wxString url = _T("");

            wxBeginBusyCursor();
            for(int j = 0; url == _T("") && j < 10*settings->timeout; ++j)
            {
               url = wxHTTP_POST(_T("pastebin.com"),_T("api/api_post.php"),params);
               wxMilliSleep(100);
            }
            wxEndBusyCursor();
            if(url == _T("") || url.Contains(_T("bad%20api%20request")))
               cbMessageBox(_T("Could not connect to http://www.pastebin.com\nPlease retry later."),_T("Connection Error"),wxICON_ERROR);
            else
            {
               if(settings->open_in_browser) wxLaunchDefaultBrowser(url);
               if(settings->copy_to_clipboard && wxTheClipboard->Open())
               {
                  wxTheClipboard->Clear();
                  wxTheClipboard->SetData( new wxTextDataObject(url) );
                  wxTheClipboard->Close();
               }
            }
         }
      }
   }
}




